import { ObjectType } from '@src/types';
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { Repository } from 'typeorm';
import { Validator, isUUID, isInt, isMobilePhone, isEmail } from 'class-validator';

@Injectable()
export class BaseService {
  private tableModel: any;
  public validator: Validator;
  constructor(tableModel: Repository<any>) {
    this.tableModel = tableModel;
    this.validator = new Validator();
  }

  /**
   * @Description: 判断是否为uuid
   * @param {type}
   * @return:
   */
  public isUUID(id: string): boolean {
    return isUUID(id);
  }

  /**
   * @Description: 判断是否为id
   * @param {type}
   * @return:
   */
  public isInt(id: string): boolean {
    return isInt(Number(id));
  }

  /**
   * @Description: 判断是否为手机号
   * @param {type}
   * @return:
   */
  public isMobilePhone(phone: string): boolean {
    return isMobilePhone(phone, 'zh-CN');
  }

  /**
   * @Description: 判断是否为邮箱
   * @param {type}
   * @return:
   */
  public isEmail(id: string): boolean {
    return isEmail(id);
  }

  /**
   * @Description: 判断一个实体类中是否含有该id
   * @param {type}
   * @return:
   */
  public hasId(entity: any): boolean {
    return this.tableModel.hasId(entity)
  };

  /**
   * @Description: 获取实体类中的id
   * @param {type}
   * @return:
   */
  public getId(entity: any): any {
    return this.tableModel.getId(entity);
  };

  /**
   * @Description: 保存的方法
   * @param {type}
   * @return:
   */
  public async save(entity: any, options?: any): Promise<any> {
    return this.tableModel.save(entity, options);
  }

  /**
   * @Description: 创建数据的方法
   * @param {type}
   * @return:
   */
  public async create(data: ObjectType): Promise<any> {
    return await this.tableModel.create(data);
  }

  /**
   * @Description: 根据条件计算条数
   * @param {type}
   * @return:
   */
  public async count(options?: ObjectType): Promise<number> {
    return await this.tableModel.count(options);
  }

  /**
   * @Description: 查找到第一条数据
   * @param {type}
   * @return:
   */
  public async findOne(options?: ObjectType): Promise<any | undefined> {
    return await this.tableModel.findOne({ where: options });
  }

  /**
   * @Description: 根据id查询出一条数据
   * @param {type}
   * @return:
   */
  public async findById(id: string): Promise<any> {
    if (this.isUUID(id)) {
      return await this.tableModel.findOne({ uuid: id });
    } else if (this.isInt(id)) {
      return await this.tableModel.findOne({ id });
    } else {
      throw new HttpException(`传递的id必须是整形或者是uuid字符串,你传递的是:${id}`, HttpStatus.OK);
    }
  }

  /**
   * @Description: 查询一个ids列表
   * @param {type}
   * @return:
   */
  public async findByIds(ids: any[], options?: ObjectType): Promise<any[]> {
    return await this.tableModel.findByIds(ids, { where: options });
  }

  /**
   * @Description: 查询到全部的数据
   * @param {type}
   * @return:
   */
  public async find(options?: ObjectType): Promise<any[]> {
    return await this.tableModel.find({ where: options });
  }
  /**
   * @Description: 分页单表查询数据(适合单表)
   * @param {type}
   * @return:
   */
  public async findPage(options?: { [propsName: string]: any }): Promise<any> {
    let { pageSize, pageNumber, ...others } = options;
    pageSize = pageSize || 10;
    pageNumber = pageNumber || 1;
    if (!this.isInt(pageSize) || !this.isInt(pageNumber)) {
      throw new HttpException(`传递的pageSize:${pageSize},pageNumber:${pageNumber}其中一个不是整数`, HttpStatus.OK);
    } else {
      const [result, total] = await this.tableModel.findAndCount({
        skip: (pageNumber - 1) * pageSize,
        take: pageSize,
        order: {
          createdAt: 'DESC',
        },
        where: {
          ...others,
        },
      });
      return {
        result,
        total
      };
    }
  }
  /**
     * @Description: 不分页单表查询数据(适合单表)
     * @param {type}
     * @return:
     */
  public async findNoPage(options?: { [propsName: string]: any }): Promise<any> {
    const { ...others } = options;
    const [result, total] = await this.tableModel.findAndCount({
      order: {
        createdAt: 'DESC',
      },
      where: {
        ...others,
      },
    });
    return {
      result,
      total
    };
  }
  /**
   * @Description: 根据id获取uuid删除数据
   * @param {type}
   * @return:
   */
  public async deleteById(id: string): Promise<any> {
    if (isInt(id)) {
      return await this.tableModel.delete({ uuid: id });
    } else if (this.isInt(id)) {
      return await this.tableModel.delete({ id });
    } else {
      throw new HttpException(`传递的id必须是整形或者是uuid字符串,你传递的是:${id}`, HttpStatus.OK);
    }
  }

  /**
   * @Description: 根据id更新数据
   * @param {type}
   * @return:
   */
  public async updateById(id: string, data: any): Promise<any> {
    if (isUUID(id)) {
      return await this.tableModel.update({ uuid: id }, data);
    } else if (this.isInt(id)) {
      return await this.tableModel.update({ id }, data);
    } else {
      throw new HttpException(`传递的id必须是整形或者是uuid字符串,你传递的是:${id}`, HttpStatus.OK);
    }
  }

  /**
   * @Description: 自己写sql语句
   * @param {type}
   * @return:
   */
  public async query(query: string, parameters?: any[]): Promise<any> {
    return await this.tableModel.query(query, parameters);
  }
}
